package log

import (
	"fmt"
	"runtime"
	"strings"
)

const (
	HI_LOG_LEVEL_INVAILD int8 = -1
)

type HiLogLevel struct {
	Val int8
}

func new_hi_log_level() *HiLogLevel {
	return &HiLogLevel{
		Val: HI_LOG_LEVEL_INVAILD,
	}
}

type HiLog struct {
	Level_info       HiLogLevel
	Level_trace      HiLogLevel
	Level_debug      HiLogLevel
	Level_alarm      HiLogLevel
	Level_warning    HiLogLevel
	Level_error      HiLogLevel
	Level_always_out HiLogLevel
	Write            func(level int8, log string)
}

var instance HiLog

func Instance() HiLog {
	if nil == &instance {
		instance = *NewHiLog()
	}
	return instance
}

func NewHiLog() *HiLog {
	return &HiLog{
		Level_info:       *new_hi_log_level(),
		Level_trace:      *new_hi_log_level(),
		Level_debug:      *new_hi_log_level(),
		Level_alarm:      *new_hi_log_level(),
		Level_warning:    *new_hi_log_level(),
		Level_error:      *new_hi_log_level(),
		Level_always_out: *new_hi_log_level(),
	}
}
func (log *HiLog) Info(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_info.Val, logMsg)
}
func (log *HiLog) Trace(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_trace.Val, logMsg)
}
func (log *HiLog) Debug(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_debug.Val, logMsg)
}
func (log *HiLog) Alarm(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_alarm.Val, logMsg)
}
func (log *HiLog) Warning(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_warning.Val, logMsg)
}
func (log *HiLog) Error(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_error.Val, logMsg)
}
func (log *HiLog) Always_out(msg string) {
	stackText := getStrackText()
	logMsg := fmt.Sprintf("%s %s", stackText, msg)
	log.Write(log.Level_always_out.Val, logMsg)
}

func getStrackText() string {
	pc, file, line, ok := runtime.Caller(2 )
	pcName := runtime.FuncForPC(pc).Name()
	if !ok {
		file = "???"
		line = 1
	} else {
		slash := strings.LastIndex(file, "/")
		if slash >= 0 {
			file = file[slash+1:]
		}
	}
	return fmt.Sprintf("[file:%s] [line:%d][%s]", file, line, pcName)
}

func (log *HiLog) Debugf(format string, args ...interface{}) {
	log.Debug(fmt.Sprintf(format, args...))
}